package cn.hiapi.shopkeeper.service;

import cn.hiapi.basic.entity.BasicEntity;
import cn.hiapi.shop.entity.shop.Shop;
import cn.hiapi.shopkeeper.entity.activity.*;
import cn.hiapi.shopkeeper.enums.ActivityType;
import cn.hiapi.utils.DateUtils;
import cn.hiapi.utils.ImageUtils;
import cn.hiapi.utils.RandomUtils;
import com.alipay.api.internal.util.file.IOUtils;
import com.google.common.collect.Lists;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.font.TextAttribute;
import java.awt.image.BufferedImage;
import java.io.*;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.AttributedString;
import java.util.*;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author AdinZ
 * @date 2023/1/11 11:42
 */

public class Shopkeeper {
    private static final int totalSize = 100 * 100;

    private static final Map<ActivityType, List<String>> thumbTemplate = new ConcurrentHashMap<>();

    static {
        for (ActivityType value : ActivityType.values()) {
            thumbTemplate.put(value, Lists.newArrayList());
        }
        thumbTemplate.put(ActivityType.APPLY, Lists.newArrayList(
                "https://shopkeeper-sx.oss-cn-hangzhou.aliyuncs.com/upload/2023-03-09/3068888141989212161.jpg",
                "https://shopkeeper-sx.oss-cn-hangzhou.aliyuncs.com/upload/2023-03-09/3068888141976629248.jpg",
                "https://shopkeeper-sx.oss-cn-hangzhou.aliyuncs.com/upload/2023-03-09/3068888141980823552.jpg"
        ));
        thumbTemplate.put(ActivityType.SOLITAIRE, Lists.newArrayList(
                "https://shopkeeper-sx.oss-cn-hangzhou.aliyuncs.com/upload/2023-03-09/3068888141985017856.jpg",
                "https://shopkeeper-sx.oss-cn-hangzhou.aliyuncs.com/upload/2023-03-09/3068888143658545152.jpg",
                "https://shopkeeper-sx.oss-cn-hangzhou.aliyuncs.com/upload/2023-03-09/3068888143658545153.jpg"
        ));
        thumbTemplate.put(ActivityType.BARGAIN, Lists.newArrayList(
                "https://shopkeeper-sx.oss-cn-hangzhou.aliyuncs.com/upload/2023-03-09/3068888141989212162.jpg",
                "https://shopkeeper-sx.oss-cn-hangzhou.aliyuncs.com/upload/2023-03-09/3068888141989212160.jpg",
                "https://shopkeeper-sx.oss-cn-hangzhou.aliyuncs.com/upload/2023-03-09/3068888143142645760.jpg"
        ));
        thumbTemplate.put(ActivityType.SPIKE, Lists.newArrayList(
                "https://shopkeeper-sx.oss-cn-hangzhou.aliyuncs.com/upload/2023-03-09/3068888143146840064.jpg",
                "https://shopkeeper-sx.oss-cn-hangzhou.aliyuncs.com/upload/2023-03-09/3068888143184588800.jpg",
                "https://shopkeeper-sx.oss-cn-hangzhou.aliyuncs.com/upload/2023-03-09/3068888143255891968.jpg"
        ));
        thumbTemplate.put(ActivityType.GROUP, Lists.newArrayList(
                "https://shopkeeper-sx.oss-cn-hangzhou.aliyuncs.com/upload/2023-03-09/3068888143281057792.jpg",
                "https://shopkeeper-sx.oss-cn-hangzhou.aliyuncs.com/upload/2023-03-09/3068888143654350848.jpg",
                "https://shopkeeper-sx.oss-cn-hangzhou.aliyuncs.com/upload/2023-03-09/3068888143654350849.jpg"
        ));

        thumbTemplate.put(ActivityType.VOTE, Lists.newArrayList(
                "https://shopkeeper-sx.oss-cn-hangzhou.aliyuncs.com/upload/2023-03-09/3068888143998283776.jpg",
                "https://shopkeeper-sx.oss-cn-hangzhou.aliyuncs.com/upload/2023-03-09/3068888144027643904.jpg",
                "https://shopkeeper-sx.oss-cn-hangzhou.aliyuncs.com/upload/2023-03-09/3068888144044421120.jpg"
        ));

    }


    public static List getActivityThumbTemplate(ActivityType type) {
        return thumbTemplate.get(type);
    }

    /**
     * 砍价算法
     *
     * @param price      总价
     * @param cutPrice   已砍总价
     * @param totalCount 总数量
     * @param cutCount   已砍数量
     * @return
     */
    public static BigDecimal activityBargain(BigDecimal price, BigDecimal cutPrice, long totalCount, long cutCount) {
        //此次砍价的最低钱数（总价-已砍总价/总次数-已砍次数）（相当于是向上随机）（转换为单位分）
        Integer min = (price.subtract(cutPrice)).divide(BigDecimal.valueOf(totalCount).subtract(new BigDecimal(cutCount)), 2, BigDecimal.ROUND_UP).multiply(new BigDecimal(100)).intValue();
        //此次砍价的最高钱数（最低价格的2倍）
        //这个倍数越高，砍价的幅度跳动越大。建议设置到1-2.（不能超过2.因为有可到导致总刀数不准确）
        Integer max = min * 2;
        BigDecimal res = new BigDecimal(min + new Random().nextInt(max - min)).divide(BigDecimal.valueOf(100), 2, BigDecimal.ROUND_UP);
        if (totalCount - cutCount == 1) {
            return price.subtract(cutPrice);
        }
        return res;
    }

    /**
     * 抽奖算法,
     * 直接根据概率返回抽奖结果
     */
    public static boolean lottery(BigDecimal rate, int lottery) {
        if (rate == null || rate.compareTo(BigDecimal.ZERO) <= 0) return false;
        if (rate.compareTo(BigDecimal.valueOf(100)) >= 0) return true;


        List<Boolean> list = new ArrayList<>();
        int value = rate.multiply(BigDecimal.valueOf(100)).intValue();
        for (int i = 0; i < totalSize - value + lottery; i++) {
            list.add(false);
        }
        for (int i = 0; i < value - lottery; i++) {
            list.add(true);
        }
        Collections.shuffle(list);
        List<Integer> integers = new ArrayList<>();
        for (int i = 0; i < 100; i++) {
            integers.add(RandomUtils.randomInt(0, list.size()));
        }
        Collections.shuffle(integers);
        int randomInt = RandomUtils.randomInt(0, integers.size());
        Integer integer = integers.get(randomInt);
        return list.get(integer);
    }


    public static long lottery(Map<Long, BigDecimal> map) {
        List<Long> list = new ArrayList<>();
        long totalSize = 100 * 100;
        map.forEach((id, rate) -> list.addAll(makeLotteryFull(id, rate)));
        int size = list.size();
        if (size <= totalSize) {
            for (int i = 0; i < totalSize - size; i++) {
                list.add(0L);
            }
        }
        Collections.shuffle(list);
        List<Integer> integers = new ArrayList<>();
        for (int i = 0; i < 100; i++) {
            integers.add(RandomUtils.randomInt(0, list.size()));
        }
        Collections.shuffle(integers);
        int randomInt = RandomUtils.randomInt(0, integers.size());
        Integer integer = integers.get(randomInt);
        return list.get(integer);
    }


    /**
     * 需要填充数据
     *
     * @param id
     * @param rate
     * @return
     */
    private static List<Long> makeLottery(long id, BigDecimal rate) {
        List<Long> list = new ArrayList<>();
        int value = rate.multiply(BigDecimal.valueOf(100)).intValue();
        for (int i = 0; i < totalSize - value; i++) {
            list.add(0L);
        }
        for (int i = 0; i < value; i++) {
            list.add(id);
        }
        return list;
    }

    /**
     * 不填充其他数据
     *
     * @param id
     * @param rate
     * @return
     */
    private static List<Long> makeLotteryFull(long id, BigDecimal rate) {
        List<Long> list = new ArrayList<>();
        int value = rate.multiply(BigDecimal.valueOf(100)).intValue();
        for (int i = 0; i < value; i++) {
            list.add(id);
        }
        return list;
    }


    /**
     * 喜糖转 余额
     *
     * @param amount 喜糖金额
     * @param rate   系统与余额汇率
     * @return
     */
    public static BigDecimal sugarToMoney(BigDecimal amount, BigDecimal rate) {
        BigDecimal divide = amount.divide(rate, 2, RoundingMode.HALF_EVEN);
        return divide;
    }

    /**
     * 余额转喜糖
     *
     * @param money 余额
     * @param rate  喜糖
     * @return
     */
    public static BigDecimal moneyToSugar(BigDecimal money, BigDecimal rate) {
        return money.multiply(rate);
    }

    /**
     * 生成分享图片
     *
     * @param activity
     * @param expand
     */
    public static void generateShareImage(Activity activity, BasicEntity expand, Shop shop, byte[] qrcode, OutputStream outputStream) {
        final int width = 375 * 2;
        final int height = 648 * 2;


        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics graphics = null;
        try {
            graphics = image.createGraphics();
            ((Graphics2D) graphics).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            ((Graphics2D) graphics).setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
            ((Graphics2D) graphics).setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
            graphics.setColor(new Color(255, 255, 255));
            graphics.fillRect(0, 0, width, height);
            ImageUtils.drawImage(graphics, shop.getLogo(), 34 * 2, 34 * 2, 15 * 2, 15 * 2);
            ImageUtils.drawString(graphics, shop.getName(), Color.BLACK, 15 * 2f, 56 * 2, 21 * 2);
            if (activity.getType() != ActivityType.CARD)
                ImageUtils.drawImage(graphics, ImageUtils.roundImage(activity.getThumb(), 15 * 2), 345 * 2, 345 * 2, 15 * 2, 64 * 2);
            else {
                ImageUtils.drawImage(graphics, createCardImage(shop, activity, (ActivityCard) expand), 345 * 2, 345 * 2, 15 * 2, 64 * 2);
            }
            ImageUtils.drawString(graphics, activity.getTitle(), Color.BLACK, Font.BOLD, 18 * 2f, 15 * 2, 424 * 2);


            BufferedImage footerBg = ImageUtils.createImage(new Color(246, 222, 199), 375 * 2, 122 * 2);
            ImageUtils.drawImage(graphics, footerBg, 375 * 2, 122 * 2, 0, 526 * 2);

            switch (activity.getType()) {
                case APPLY:
                case BARGAIN:
                case GROUP:
                case SPIKE:
                case CARD:
                    BigDecimal price = BigDecimal.ZERO;
                    if (activity.getType() == ActivityType.APPLY)
                        price = ((ActivityApply) expand).getPrice();
                    else if (activity.getType() == ActivityType.BARGAIN)
                        price = ((ActivityBargain) expand).getMinPrice();
                    else if (activity.getType() == ActivityType.GROUP)
                        price = ((ActivityGroupBuy) expand).getPrice();
                    else if (activity.getType() == ActivityType.SPIKE)
                        price = ((ActivitySpike) expand).getPrice();
                    else if (activity.getType() == ActivityType.CARD)
                        price = ((ActivityCard) expand).getPrice();
                    //有最低价格的
                    ImageUtils.drawString(graphics, "最低价¥", Color.decode("#FE496A"), 14 * 2f, 15 * 2, 488 * 2);
                    ImageUtils.drawString(graphics, price.setScale(2, RoundingMode.HALF_EVEN).toPlainString(),
                            Color.decode("#FE496A"), Font.BOLD, 19 * 2f, 67 * 2, 485 * 2);

                    break;
                case VOTE:
                case LOTTERY:
                case LOTTERY_AD:
                case SOLITAIRE:
                    //不需要价格的
                    break;
            }
            ImageUtils.drawString(graphics, "长按识别二维码参与" + getShareTextSub(activity.getType()), Color.decode("#B08252"), 14 * 2, 15 * 2, 591 * 2);
            ImageUtils.drawString(graphics, getShareText(activity.getType()), Color.decode("#B08252"), Font.BOLD, 16 * 2, 15 * 2, 564 * 2);
            if (qrcode != null)
                ImageUtils.drawImage(graphics, ImageIO.read(new ByteArrayInputStream(qrcode)), 91 * 2, 91 * 2, 268 * 2, 541 * 2);
            ImageIO.write(image, "png", outputStream);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        } finally {
            if (graphics != null) graphics.dispose();
        }
    }


    private static BufferedImage createCardImage(Shop shop, Activity activity, ActivityCard expand) throws IOException {
        BufferedImage image = new BufferedImage(345 * 2, 345 * 2, BufferedImage.TYPE_INT_RGB);
        Graphics2D graphics = image.createGraphics();
        graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        graphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
        graphics.setColor(Color.decode(expand.getColor()));
        graphics.fillRect(0, 0, 345 * 2, 345 * 2);
        ImageUtils.drawString(graphics, expand.getTitle(), Color.WHITE, 16 * 2, 15 * 2, 30 * 2);
        String text = "¥" + expand.getPrice() + "/" + expand.getNumber() + "次";
        ImageUtils.drawString(graphics, text, Color.WHITE, Font.BOLD, 25 * 2, 15 * 2, (345 - 15 - 20 - 50) * 2);


        String text1 = "¥" + activity.getPrice();
        AttributedString as = new AttributedString(text1);
        as.addAttribute(TextAttribute.SWAP_COLORS, Color.GRAY);
        as.addAttribute(TextAttribute.FONT, ImageUtils.loadFont().deriveFont(14f));
        as.addAttribute(TextAttribute.STRIKETHROUGH, TextAttribute.STRIKETHROUGH_ON, 1, text1.length());
        graphics.drawString(as.getIterator(), 200, 345 - 15 - 20 - 30);

        String expire = DateUtils.format(activity.getUseStart()) + "-" + DateUtils.format(activity.getUseEnd()) + "有效";
        ImageUtils.drawString(graphics, expire, Color.WHITE, 14 * 2, 15 * 2, (345 - 15 - 20) * 2);
        return ImageUtils.roundImage(image, 20);
    }

    private static String getShareText(ActivityType type) {
        switch (type) {
            case SPIKE:
                return "邀你来拼手速";
            case VOTE:
                return "邀你来投票";
            case SOLITAIRE:
                return "邀你来接龙";
            case LOTTERY:
            case LOTTERY_AD:
                return "邀你来抽奖";
            case GROUP:
                return "邀你来拼团";
            case BARGAIN:
                return "邀你来砍价";
            case APPLY:
                return "邀你来报名";
            default:
                return "邀你来参与";
        }

    }

    private static String getShareTextSub(ActivityType type) {
        switch (type) {
            case SPIKE:
                return "秒杀";
            case VOTE:
                return "投票";
            case SOLITAIRE:
                return "接龙";
            case LOTTERY:
            case LOTTERY_AD:
                return "抽奖";
            case GROUP:
                return "拼团";
            case BARGAIN:
                return "砍价";
            case APPLY:
                return "报名";
            default:
                return "助力";
        }
    }

    public static void main(String[] args) throws IOException {
        Shop shop = new Shop();
        shop.setLogo("https://shopkeeper-sx.oss-cn-hangzhou.aliyuncs.com/upload/2023-02-19/3062396549434503168.jpeg");
        shop.setName("测试店铺");

        Activity activity = new Activity();
        activity.setTitle("测试商品名字");
        activity.setThumb("https://shopkeeper-sx.oss-cn-hangzhou.aliyuncs.com/upload/2023-02-22/3063412746217123840.png");
        activity.setType(ActivityType.LOTTERY);

        ActivityCard card = new ActivityCard();
        card.setPrice(BigDecimal.valueOf(99.99));
        card.setTitle("测试次卡活动");
        card.setColor("#B08252");
        card.setNumber(3);


        byte[] bytes = IOUtils.toByteArray(new FileInputStream("d:/2.png"));

        generateShareImage(activity, card, shop, bytes, new FileOutputStream("d:/1.png"));

    }


}
